function Metro(e){var v=this;this.elemMetro=document.getElementById(e),this.Lines=new Array,this.camera=new function(){var o=this,n=30,i=new Number,r=(new Array,0),s=new Number,a=new Number,h=new Number,l=new Number;this.setScreen=function(){var e=v.elemMetro.offsetWidth,t=v.elemMetro.offsetHeight;a=Math.min(e,t),h=e/2,l=t/2,i=a/2/Math.tan(n/180*Math.PI/2)},this.setDefaultViewDistance=function(){s=11/Math.tan(n/180*Math.PI/2)},this.setDefaultAverageHeight=function(){for(var e=r=0,t=0;t<v.Lines.length;t++)for(var n=0;n<v.Lines[t].Stations.length;n++)r+=v.Lines[t].Stations[n].Coords[2],e++;0<e&&(r/=e)},this.setViewDistance=function(e){e<0&&(e=0);s=e},this.getViewDistance=function(){return s},this.multiplyViewDistance=function(e){s*=e},this.setAngles=function(e,t){var n=o;t=Math.max(Math.min(t,90),-90),n.phi=e,n.theta=t,e=e/180*Math.PI,t=t/180*Math.PI;var a=Math.cos(e),i=Math.sin(e),r=Math.cos(t),s=Math.sin(t);n.viewMatrix=[[-i,a,0],[-s*a,-s*i,r],[r*a,r*i,s]]},this.getAngles=function(){return{phi:o.phi,theta:o.theta}},this.addAngles=function(e,t){var n=o;n.setAngles(n.phi+e,n.theta+t)},this.applyMatrix=function(e){var t=o;return[t.viewMatrix[0][0]*e[0]+t.viewMatrix[0][1]*e[1]+t.viewMatrix[0][2]*e[2],t.viewMatrix[1][0]*e[0]+t.viewMatrix[1][1]*e[1]+t.viewMatrix[1][2]*e[2],t.viewMatrix[2][0]*e[0]+t.viewMatrix[2][1]*e[1]+t.viewMatrix[2][2]*e[2]]},this.calcView=function(e){var t=o,n=[e[0],e[1],e[2]];n[2]-=r,(n=t.applyMatrix(n))[2]-=s,n[2]=0<n[2]?-1e-6:n[2];var a=-n[2]/i;return[h+n[0]/a,l-n[1]/a,n[2]]},this.optimizeSizeToScreen=function(e){return Math.min(e/750*a,e)},this.emulateVisibleSize=function(e){if((e+=s)<-5)return.8;if(5<e)return 5/4;var t=(e+5)/10;return(1-t)/(5/4)+t*(5/4)},this.getMetersPerCm=function(e){var t=s/i*e/2.54*1e3;return[t,t/v.geo.getDepthScale()]},this.setScreen(),this.setDefaultViewDistance(),this.setAngles(-90,45)},this.geo=new function(){var n=this,a=55.755793*Math.PI/180,i=37.617678*Math.PI/180;this.getDepthScale=function(){return 50},this.thetaPhi2XY=function(e,t){return e=e*Math.PI/180,t=t*Math.PI/180,[6371.21*Math.cos(e)*(t-i),6371.21*(e-a)]},this.geoCoords2XYZ=function(e){var t=n.thetaPhi2XY(e[0],e[1]);return t.push(50*(e[2]+e[3])/1e3),t}},this.filter=new function(){var n=this,a=(new Date).getFullYear(),i=a;this.filterYears=!0,this.getSelectedYear=function(){return i},this.getCurrentYear=function(){return a},this.setSelectedYear=function(e){var t=parseInt(e);1935<=t&&t<=a&&(i=t)},this.isStationDisplayed=function(e){if(!n.filterYears)return!0;for(var t=e.NamesYears.length-1;0<=t;t--)if(e.NamesYears[t][1]<=i)return void 0===e.NamesYears[t][2]||e.NamesYears[t][2]>i;return!1},this.isTunnelDisplayed=function(e){return n.isStationDisplayed(e.station1)&&n.isStationDisplayed(e.station2)},this.checkLine=function(e){for(var t=e,n=[],a=1;a<t.Stations.length-1;a++)(t.Stations[a-1].isHidden()||!t.Stations[a].isHidden()||t.Stations[a+1].isHidden())&&("Молодежная"!=t.Stations[a].getName()&&"Molodyozhnaya"!=t.Stations[a].getName()||t.Stations[a].isHidden())||n.push(t.Stations[a]);if(0<n.length)for(var i=0;i<n.length;i++)for(var a=0;a<t.Tunnels.length;a++)(t.Tunnels[a].station1==n[i]||t.Tunnels[a].station2==n[i]&&"Молодежная"!=n[i].getName()&&"Molodyozhnaya"!=n[i].getName())&&"Деловой центр, КСЛ"!=n[i].getName()&&"Delovoy Tsentr, KSL"!=n[i].getName()&&t.Tunnels[a].show()}},this.draw=function(){for(var e=v,t=0;t<e.Lines.length;t++)e.Lines[t].draw()},this.applyFilter=function(){for(var e=v,t=0;t<e.Lines.length;t++)e.Lines[t].applyFilter()},this.rotate=function(e,t){var n=v;return n.camera.addAngles(e,t),n.draw(),!1},this.zoom=function(e){var t=v;return t.camera.multiplyViewDistance(e),t.draw(),!1},this.updateSize=function(){var e=v;return e.camera.setScreen(),e.draw(),!1},this.addLine=function(e,t,n){var a=v,i=new d(n);i.addStations(e,t),a.Lines.push(i),a.camera.setDefaultAverageHeight()},this.setInterchanges=function(e){for(var t=v,n=new d("interchanges"),a=0;a<e.length;a++){var i=null,r=null;e:for(var s=0;s<t.Lines.length;s++)for(var o=0;o<t.Lines[s].Stations.length;o++)if(t.Lines[s].Stations[o].getName()==e[a][0]&&(i=t.Lines[s].Stations[o]),t.Lines[s].Stations[o].getName()==e[a][1]&&(r=t.Lines[s].Stations[o]),i&&r)break e;if(i&&r){n.addTunnel(i,r);var h=Math.sqrt(Math.pow(i.Coords[0]-r.Coords[0],2)+Math.pow(i.Coords[1]-r.Coords[1],2));if(h<.1){t.camera.calcView(r.Coords)[2]>t.camera.calcView(i.Coords)[2]?i.elemStation.style.paddingTop="8px":r.elemStation.style.paddingTop="8px"}}}t.Lines.push(n)},this.inputGetParams=function(){var e=v,t=readGetParams(),n=e.camera.getAngles(),a=e.camera.getViewDistance(),i=e.filter.getSelectedYear();t.p&&(n.phi=Number(t.p));t.t&&(n.theta=Number(t.t));t.d&&(a=Number(t.d));t.y&&(i=Number(t.y));e.camera.setAngles(n.phi,n.theta),e.camera.setViewDistance(a),e.filter.setSelectedYear(i)},this.outputGetParams=function(){var e=v,t={p:e.camera.getAngles().phi,t:e.camera.getAngles().theta,d:e.camera.getViewDistance()};e.filter.getSelectedYear()!=e.filter.getCurrentYear()?t.y=e.filter.getSelectedYear():t.y="";writeGetParams(t)},this.useGPU=!1;var o=parseInt(getCssValue("#metro ul span","height")),h=parseInt(getCssValue("#metro ul span","marginTop")),l=1==parseInt(decodeURI(readGetParams().en));function d(e){var i=this;this.elemLine=document.createElement("ul"),this.Stations=new Array,this.Tunnels=new Array,this.lineId=e,this.draw=function(){for(var e=i,t=0;t<e.Stations.length;t++)e.Stations[t].draw();for(var t=0;t<e.Tunnels.length;t++)e.Tunnels[t].draw()},this.applyFilter=function(){for(var e=i,t=0;t<e.Stations.length;t++)e.Stations[t].applyFilter();for(var t=0;t<e.Tunnels.length;t++)e.Tunnels[t].applyFilter();v.filter.checkLine(e)},this.addStations=function(e,t){for(var n=i,a=0;a<e.length;a++)n.Stations.push(new r(e[a],t[a])),0<a&&n.Tunnels.push(new s(n.Stations[a-1],n.Stations[a]))},this.addTunnel=function(e,t){i.Tunnels.push(new s(e,t))};var n=parseInt(getCssValue("#"+i.lineId+" span","height")),a=parseInt(getCssValue("#"+i.lineId+" span","marginTop"));function r(e,t){var r=this;this.NamesYears=t,this.elemStation=document.createElement("li"),this.geoCoords=e,this.Coords=v.geo.geoCoords2XYZ(e),this.renderedCoords,this.lastRenderedCoords,this.getYear=function(){return r.NamesYears[0][1]},this.getName=function(e){if(void 0===e)return r.NamesYears[r.NamesYears.length-1][0];for(var t=r.NamesYears.length-1;0<=t;t--)if(r.NamesYears[t][1]<=e&&(void 0===r.NamesYears[t][2]||r.NamesYears[t][2]>e))return r.NamesYears[t][0];return""},this.show=function(){r.elemStation.style.display=""},this.hide=function(){r.elemStation.style.display="none"},this.isHidden=function(){return"none"==r.elemStation.style.display},this.makeDescription=function(e){var t=r;t.elemStation.innerHTML=t.getName(e),t.elemStation.setAttribute("data-tooltip","<b>"+t.getName(e)+"</b> ("+t.getYear()+(l?")<br>":" г.)<br>")+(l?"Coordinates: ":"Координаты: ")+Math.round(10*t.Coords[0])/10+(l?" km, ":" км, ")+Math.round(10*t.Coords[1])/10+(l?" km<br>":" км<br>")+(l?"Depth: ":"Глубина: ")+(0<t.geoCoords[2]?"+":"")+t.geoCoords[2]+(l?" m (":" м (")+(t.geoCoords[2]+t.geoCoords[3])+(l?" above sea level)":" над ур. моря)")+"<br><span>"+(l?"(Click to select a line)":"(Кликните для выделения линии)")+"</span>")},this.applyFilter=function(){var e=r;v.filter.isStationDisplayed(e)?(e.show(),e.makeDescription(v.filter.getSelectedYear())):e.hide()},this.draw=function(){var e=r;e.lastRenderedCoords=e.renderedCoords,e.renderedCoords=v.camera.calcView(e.Coords);var t=v.camera.emulateVisibleSize(e.renderedCoords[2]),n=t*v.camera.optimizeSizeToScreen(12),a="",i="";v.useGPU&&(a="translate("+e.renderedCoords[0]+"px, "+e.renderedCoords[1]+"px)",i=" scale("+n/v.camera.optimizeSizeToScreen(12)+")");e.elemStation.style.cssText=(v.useGPU?"-ms-transform:"+a+i+";-webkit-transform:"+a+i+";-moz-transform:"+a+i+";-o-transform:"+a+i+";transform:"+a+i+";":"left:"+e.renderedCoords[0]+"px;top:"+e.renderedCoords[1]+"px;line-height:"+n+"px;background-size:"+n+"px;margin:"+-n/2+"px 0 0 "+-n/2+"px;")+"z-index:"+Math.round(100*(e.renderedCoords[2]+v.camera.getViewDistance()+30))+";opacity:"+Math.min(1,.9*t)+";display:"+e.elemStation.style.display+";padding-top:"+e.elemStation.style.paddingTop+";"},this.applyFilter(),i.elemLine.appendChild(this.elemStation)}function s(e,t){var c,m=this,p=n||o,f=a||h,g=0;this.station1=e,this.station2=t,this.elemTunnel=document.createElement("span"),this.show=function(){m.elemTunnel.style.display=""},this.hide=function(){m.elemTunnel.style.display="none"},this.isHidden=function(){return"none"==m.elemTunnel.style.display},this.applyFilter=function(){var e=m;v.filter.isTunnelDisplayed(e)?e.show():e.hide()},this.draw=function(){var e=m,t=function(e){var t,n,a=e.station1.renderedCoords[0],i=e.station1.renderedCoords[1],r=e.station2.renderedCoords[0]-e.station1.renderedCoords[0],s=e.station2.renderedCoords[1]-e.station1.renderedCoords[1];if(0==r&&0==s)return{x1:a,y1:i,x2:a,y2:i};Math.abs(r)>Math.abs(s)?(t=(-8e3-a)/r,n=(8e3-a)/r):(t=(-8e3-i)/s,n=(8e3-i)/s);var o=Math.min(t,n),h=Math.max(t,n),l=Math.max(0,o),d=Math.min(1,h);return l<d?{x1:a+l*r,y1:i+l*s,x2:a+d*r,y2:i+d*s}:{x1:a+o*r,y1:i+o*s,x2:a+o*r,y2:i+o*s}}(e),n=t.x2-t.x1,a=t.y2-t.y1,i=Math.sqrt(Math.pow(n,2)+Math.pow(a,2)),r=Math.atan2(a,n)/Math.PI*180;r=function(e){e+=g,null!=c&&(180<e-c&&(e-=360,g-=360),e-c<-180&&(e+=360,g+=360));return e}(r),c=r;var s=Math.min(e.station1.renderedCoords[2],e.station2.renderedCoords[2]),o=(e.station1.renderedCoords[2]+e.station2.renderedCoords[2])/2,h=v.camera.emulateVisibleSize(o),l=" rotate("+r+"deg)",d="",u="";v.useGPU&&(d="translate("+t.x1+"px, "+t.y1+"px)",u=" scaleY("+h+")");e.elemTunnel.style.cssText=(v.useGPU?"":"left:"+t.x1+"px;top:"+t.y1+"px;height:"+h*v.camera.optimizeSizeToScreen(p)+"px;margin-top:"+h*v.camera.optimizeSizeToScreen(f)+"px;")+"width:"+i+"px;z-index:"+Math.round(100*(s+v.camera.getViewDistance()+30)-1)+";opacity:"+Math.min(1,.9*h)+";-ms-transform:"+d+l+u+";-webkit-transform:"+d+l+u+";-moz-transform:"+d+l+u+";-o-transform:"+d+l+u+";transform:"+d+l+u+";display:"+e.elemTunnel.style.display+";"},this.elemTunnel.setAttribute("data-tooltip",(l?"Distance: ":"Расстояние: ")+Math.round(10*Math.sqrt(Math.pow(this.station2.Coords[0]-this.station1.Coords[0],2)+Math.pow(this.station2.Coords[1]-this.station1.Coords[1],2)+Math.pow((this.station2.Coords[2]-this.station1.Coords[2])/v.geo.getDepthScale(),2)))/10+(l?" km<br>":" км<br>")+(l?"Depth difference: ":"Перепад глубин: ")+Math.round(Math.abs(this.station2.Coords[2]-this.station1.Coords[2])/v.geo.getDepthScale()*1e3)+(l?" m":" м")+"<br><span>"+(l?"(Click to select a line)":"(Кликните для выделения линии)")+"</span>"),i.elemLine.appendChild(this.elemTunnel)}this.elemLine.id=e,v.elemMetro.appendChild(this.elemLine)}}